package control

import (
	"jvm/nzpJvm/instructions/base"
	"jvm/nzpJvm/runtime_area"
)

// switch语句不可以被编译成一个索引表时，将使用lookupSwitch指令
type LOOKUP_SWITCH struct {
	defaultOffset int32
	npairs        int32
	// 这一定是一个长度为偶数的数组，奇数位置是key值，下一个位置是偏移量
	matchOffsets []int32
}

func (self *LOOKUP_SWITCH) FetchOperands(reader *base.BytecodeReader) {
	// lookupSwitch指令之后的0——3个字节是填充字节
	reader.SkipPadding()
	self.defaultOffset = reader.ReadInt32()
	self.npairs = reader.ReadInt32()
	// 后面都是一个int32的键加一个int32的值，所以要乘以2
	n := self.npairs * 2
	self.matchOffsets = reader.ReadInt32s(n)

}
// 不能被编译成一个索引表的switch语句，只能用lookuoswitch指令
// 可以看出来这个指令的效率比tableswitch要低一些
// matchOffsets中的key一定是递增的，要改进的话，可以改成二分查找
func (self *LOOKUP_SWITCH) Execute(frame *runtime_area.Frame) {
	key := frame.OperandStack().PopInt()
	n := self.npairs * 2
	for i := int32(0); i < n; i += 2 {
		if key == self.matchOffsets[i] {
			offset := int(self.matchOffsets[i+1])
			base.Branch(frame, offset)
			return
		}
	}
	base.Branch(frame, int(self.defaultOffset))
}
